/**
 * *****************************************************************************
 * @file    scan.c
 * @author  Jack
 * @version 1.0.0
 * @date    2022-05-27
 * @brief   the procedure for radar scanning.
 * 
 *                 Copyright (c) 2021, Andar Technologies Inc.
 *                           www.andartechs.com
 * 
 * *****************************************************************************
 */
/*----------------------------- include --------------------------------------*/

#include "common.h"
#include "scan.h"
#include "adt3102.h"
#include "peak_single.h"
#include "adt3102_pmu.h"
#include "adt3102_dsp.h"
#include "adt3102_timer.h"
#include "adt3102_gpio.h"
#include "adt3102_tx.h"
#include "adt3102_rx.h"
#include "adt3102_uart.h"
#include "adt3102_rtc.h"
#include "static_remove.h"
#include "math.h"
#include "fft.h"
#include "adt3102_spi.h"
#include "adt3102_flash.h"
#include "spi_acquisition.h"
#include "rfc_ctype_map.h"

/*------------------------------ variable ------------------------------------*/
static dspMemoryStgrTypedef         s_dspMemoryStr;
static scanStrParasTypedef          s_scanStr;

volatile uint32 g_frameStart = 0;
volatile int32  g_sendCount   = 0;


/*------------------------------ function ------------------------------------*/
/**
 * @brief   initialize all related parameters for scanning.
 * @param   None.
 * @return  None.
 * @note
 */
void adt3102ScanInit(void)
{
    /* rf */
#if TXRXTYPE == TX1RX1
    s_scanStr.chirpStr.rx0En         = ENABLE;
    s_scanStr.chirpStr.rx1En         = ENABLE;
  #if PRIMARY_TDD_CH == TX1
    s_scanStr.chirpStr.tx0En         = DISABLE;
    s_scanStr.chirpStr.tx1En         = ENABLE;
    s_scanStr.chirpStr.PaGain0       = 0;
    s_scanStr.chirpStr.PaGain1       = 14;
  #elif PRIMARY_TDD_CH == TX0
    s_scanStr.chirpStr.tx0En         = ENABLE;
    s_scanStr.chirpStr.tx1En         = DISABLE;
    s_scanStr.chirpStr.PaGain0       = 14;
    s_scanStr.chirpStr.PaGain1       = 0;  
  #endif
  
#elif TXRXTYPE == TX1RX2
    s_scanStr.chirpStr.rx0En         = ENABLE;
    s_scanStr.chirpStr.rx1En         = ENABLE;
  
  #if PRIMARY_TDD_CH == TX1
    s_scanStr.chirpStr.tx0En         = DISABLE;
    s_scanStr.chirpStr.tx1En         = ENABLE;
    s_scanStr.chirpStr.PaGain0       = 0;
    s_scanStr.chirpStr.PaGain1       = 14;
  #elif PRIMARY_TDD_CH == TX0
    s_scanStr.chirpStr.tx0En         = ENABLE;
    s_scanStr.chirpStr.tx1En         = DISABLE;
    s_scanStr.chirpStr.PaGain0       = 14;
    s_scanStr.chirpStr.PaGain1       = 0;
  #endif
  
#elif TXRXTYPE == TX2RX2
    s_scanStr.chirpStr.rx0En         = ENABLE;
    s_scanStr.chirpStr.rx1En         = ENABLE;
    s_scanStr.chirpStr.tx0En         = ENABLE;
    s_scanStr.chirpStr.tx1En         = ENABLE;
    s_scanStr.chirpStr.PaGain0       = 14;
    s_scanStr.chirpStr.PaGain1       = 14;
#endif

    s_scanStr.chirpStr.phaseShftLut0En = DISABLE;
    s_scanStr.chirpStr.phaseShftLut1En = DISABLE;

    /* if */
    s_scanStr.chirpStr.tiaHpfEn      = DISABLE;
    s_scanStr.chirpStr.rcHpfEn       = DISABLE;
    s_scanStr.chirpStr.pgaHpfEn      = DISABLE;
    s_scanStr.chirpStr.tiaGain0      = TIA_GAIN_6DB;    // 0,6,12,18
    s_scanStr.chirpStr.pgaGain0      = PGA_GAIN_20DB;    // PGA_GAIN_30DB;
    s_scanStr.chirpStr.tiaGain1      = TIA_GAIN_6DB;
    s_scanStr.chirpStr.pgaGain1      = PGA_GAIN_20DB;    // PGA_GAIN_30DB;
    s_scanStr.chirpStr.tiaHpf        = TIA_HPF_25KHZ;   // 25,50,100,300
    s_scanStr.chirpStr.rcHpf         = RC_HPF_150KHZ;    // 150, 400
    s_scanStr.chirpStr.pgaHpf        = PGA_HPF_25KHZ;   // 100,500
    s_scanStr.chirpStr.pgaLpf        = PGA_LPF_2M;

    s_dspMemoryStr.chirpNumCfg       = CHIRP_NUM_FMCW_CONFIG;
    s_dspMemoryStr.chirpNum          = CHIRP_NUM;
    s_dspMemoryStr.chirpPeriod       = CHIRP_PERIOD;
    s_dspMemoryStr.srcADCR0          = ADC_CH0_DATA_ADDR;
    s_dspMemoryStr.srcADCR1          = ADC_CH1_DATA_ADDR;
    s_dspMemoryStr.samplePoint       = SAMPLE_POINT;
}

/**
 * @brief   adcSample.
 * @param   None.
 * @return  None.
 * @note
 */
void adcSample(void)
{
#if ENBALE_FRAME_PERIOD
    //Frame rate control using timer1
    while(g_frameStart == 0){};
    g_frameStart = 0;
#endif

    // Send chirps and sample ADC.
#if CHIRPS_TX_MODE == SINGLE_CHIRPS_MODE
    SendChirpsSingle(&s_dspMemoryStr);
#elif CHIRPS_TX_MODE == CONTINUE_CHIRPS_MODE
    SendChirpsCont(&s_dspMemoryStr);
#endif

    //do agc over adc samples
    doAGC(&s_scanStr.chirpStr, &s_dspMemoryStr);
}

/**
 * @brief   Send single chirp , collect ADC and do ragne fft.
 * @param   uint32 space.  The integer between single chip, unit: macro second
 * @param   dspMemoryStgrTypedef.
 *          See the @dspMemoryStgrTypedef member for details.
 * @return  None.
 * @note
 */
void SendChirpsSingle(dspMemoryStgrTypedef *memory)
{

    for(uint32 i = 0; i < memory->chirpNum; i++)
    {
    #if FRAME_LOWPOWER
        lowPowerSwitchPll(1, 1);
        lowPowerSwitchFast(s_scanStr.chirpStr.rx0En, \
                       s_scanStr.chirpStr.rx1En, \
                       s_scanStr.chirpStr.tx0En, \
                       s_scanStr.chirpStr.tx1En, \
                       s_scanStr.chirpStr.tiaHpf, \
                       s_scanStr.chirpStr.rcHpf, \
                       s_scanStr.chirpStr.pgaHpf
                    );
        delayUs(100, HIGH_CLOCK); //wait for RF settle
    #endif

        // send single chirp and sample adc data.
        g_sendCount = 0;
        #if PRIMARY_TDD_CH == TX1
        {
            // enable PA1 and disable PA0
            txPaEnable(DISABLE, ENABLE);
            RFC->rf_buf77g_ctrl_reg |= rf_buf77g_ctrl_reg_buff77g_en_tx1_bit;// tx1 buff enable
            RFC->rf_buf77g_ctrl_reg &= ~(rf_buf77g_ctrl_reg_buff77g_en_tx0_bit);// tx0 buff disable
        }
        #elif PRIMARY_TDD_CH == TX0
        {
            // enable PA0 and disable PA1
            txPaEnable(ENABLE, DISABLE);
            RFC->rf_buf77g_ctrl_reg |= rf_buf77g_ctrl_reg_buff77g_en_tx0_bit;// tx0 buff enable            
            RFC->rf_buf77g_ctrl_reg &= ~rf_buf77g_ctrl_reg_buff77g_en_tx1_bit;// tx1 buff disable
        }
        #endif

        timerInit(Timer0, memory->chirpPeriod, HIGH_CLOCK);
        doSendChirp(memory);
        timerOff(Timer0);

        SendDataSingle(memory, i);

    #if FRAME_LOWPOWER
        lowPowerSwitchPll(1, 0);
        lowPowerSwitchFast(0, \
                       0, \
                       0, \
                       0, \
                       s_scanStr.chirpStr.tiaHpf, \
                       s_scanStr.chirpStr.rcHpf, \
                       s_scanStr.chirpStr.pgaHpf
                    );
    #endif

        //range fft for current chirp.
        if(memory->chirpPeriod > CHIRP_PERIOD)
        {
            delayUs(memory->chirpPeriod - CHIRP_PERIOD, HIGH_CLOCK);
        }
    }
}

/**
 * @brief   Send all chirp , collect ADC and do ragne fft.
 * @param   uint32 space.  The integer between single chip, unit: macro second
 * @param   dspMemoryStgrTypedef.
 *          See the @dspMemoryStgrTypedef member for details.
 * @return  None.
 * @note
 */
void SendChirpsCont(dspMemoryStgrTypedef *memory)
{
#if FRAME_LOWPOWER
    lowPowerSwitchPll(1, 1);
    lowPowerSwitchFast(s_scanStr.chirpStr.rx0En, \
                       s_scanStr.chirpStr.rx1En, \
                       s_scanStr.chirpStr.tx0En, \
                       s_scanStr.chirpStr.tx1En, \
                       s_scanStr.chirpStr.tiaHpf, \
                       s_scanStr.chirpStr.rcHpf, \
                       s_scanStr.chirpStr.pgaHpf
                    );
    delayUs(100, HIGH_CLOCK); //wait for RF settle
#endif

    // send single chirp and sample adc data.
    #if PRIMARY_TDD_CH == TX1
    {
        // enable PA1 and disable PA0
        txPaEnable(DISABLE, ENABLE);
        RFC->rf_buf77g_ctrl_reg |= rf_buf77g_ctrl_reg_buff77g_en_tx1_bit;// tx1 buff enable
        RFC->rf_buf77g_ctrl_reg &= ~(rf_buf77g_ctrl_reg_buff77g_en_tx0_bit);// tx0 buff disable
    }
    #elif PRIMARY_TDD_CH == TX0
    {
        // enable PA0 and disable PA1
        txPaEnable(ENABLE, DISABLE);
        RFC->rf_buf77g_ctrl_reg |= rf_buf77g_ctrl_reg_buff77g_en_tx0_bit;// tx0 buff enable            
        RFC->rf_buf77g_ctrl_reg &= ~rf_buf77g_ctrl_reg_buff77g_en_tx1_bit;// tx1 buff disable
    }
    #endif

    g_sendCount = 0;
    timerInit(Timer0, memory->chirpPeriod, HIGH_CLOCK);
    doSendChirp(memory);
    timerOff(Timer0);

#if FRAME_LOWPOWER
    lowPowerSwitchPll(1, 0);
    lowPowerSwitchFast(0, \
                       0, \
                       0, \
                       0, \
                       s_scanStr.chirpStr.tiaHpf, \
                       s_scanStr.chirpStr.rcHpf, \
                       s_scanStr.chirpStr.pgaHpf
                    );
#endif
    
    SendDataCont(memory);
}

/**
 * @brief   get pointer to struct @scanStrParasTypedef.
 * @param   None.
 * @return  scanStrParasTypedef*: pointer to scanStrParasTypedef
 *          See the @scanStrParasTypedef member for details.
 * @note
 */
scanStrParasTypedef* getScanStrPara(void)
{
    return &s_scanStr;
}

/**
 * @brief   power off a few of RF modules, which take a few more
 *          time to wake up again stably.
 * @param   None.
 * @return  None.
 * @note
 */
void doPowerOffSlowRf(void)
{
    //power off Slow RF

    if(getSystemFreq() == HIGH_CLOCK_125M)
    {
        switchTo50m();
    #if UART_ENABLED
        uartInit(UART0, BAUDRATE, HIGH_CLOCK_50M);
        #if(ADT_UART_COMM_SELECT == ADT6101_UART1_COMM)
            #if(ADT6101_BOARD_SELECT != ADT6101_EXPLOER_BOARD)
                uartInit(UART1, BAUDRATE, HIGH_CLOCK_50M);
            #endif
        #endif
    #endif
    }

    tmp_lowPowerSwitchSlow(0, 0, 0, 0, &s_scanStr.chirpStr);
}

/**
 * @brief   power on a few of RF modules, which take a few more
 *          time to wake up again stably.
 * @param   None.
 * @return  None.
 * @note
 */
void doPowerOnSlowRf(void)
{
    tmp_lowPowerSwitchSlow(s_scanStr.chirpStr.rx0En, \
                            s_scanStr.chirpStr.rx1En, \
                            s_scanStr.chirpStr.tx0En, \
                            s_scanStr.chirpStr.tx1En, \
                            &s_scanStr.chirpStr);

    if(getSystemFreq() == HIGH_CLOCK_50M)
    {
        switch125MHclk();
    #if UART_ENABLED
        uartInit(UART0, BAUDRATE, HIGH_CLOCK_125M);
        #if(ADT_UART_COMM_SELECT == ADT6101_UART1_COMM)
            #if(ADT6101_BOARD_SELECT != ADT6101_EXPLOER_BOARD)
                uartInit(UART1, BAUDRATE, HIGH_CLOCK_125M);
            #endif
        #endif
    #endif
    }

    delayUs(1000, HIGH_CLOCK_125M); //wait for RF settle
}
